package de.mmis.core.tuplespace.gui;

import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.CountDownLatch;

import javax.swing.JPanel;
import javax.swing.SwingUtilities;

import org.apache.log4j.Logger;

import de.mmis.core.base.device.Device;
import de.mmis.core.base.event.Observable;
import de.mmis.core.base.event.Observer;
import de.mmis.core.base.gui.DeviceControlComponent;
import de.mmis.core.tuplespace.Tuplespace;
import de.mmis.core.tuplespace.TuplespaceException;

public class ControlComponent implements DeviceControlComponent<Tuplespace> {

	private final static Logger LOGGER = Logger
			.getLogger(ControlComponent.class);

	private static final long serialVersionUID = -7270189945775076072L;

	private Device<Tuplespace> device;
	private TuplespaceBrowserPanel panel_browser;
	private CountDownLatch panel_browser_initalized = new CountDownLatch(1);
	protected List<Observer<GUIEvent>> observers = new LinkedList<Observer<GUIEvent>>();

	@Override
	public boolean isApplicableForControlling(Class<?> clazz) {
		return Tuplespace.class.isAssignableFrom(clazz);
	}

	@Override
	public String getDisplayName(String languageCode) {
		return "Tuplespace";
	}

	@Override
	public long getPriority() {
		return 100;
	}

	@Override
	public void notify(
			Observable<? extends de.mmis.core.base.gui.GUIComponent.GUIEvent> sender,
			de.mmis.core.base.gui.GUIComponent.GUIEvent event) {
		// do nothing
	}

	@Override
	public void initialize(Class<?> clazz, final Device<Tuplespace> device,
			ClassLoader cl) {
		this.device = device;
		SwingUtilities.invokeLater(new Runnable() {
			@Override
			public void run() {
				try {
					initGUI();
				} catch (TuplespaceException e) {
					LOGGER.error("error initializing GUI", e);
				}
			}
		});
	}

	private void initGUI() throws TuplespaceException {
		panel_browser = new TuplespaceBrowserPanel(device);
		panel_browser_initalized.countDown();
	}

	/**
	 * Fires the given event, i.e. distributes it to all registered observers (
	 * {@link Observer}s).
	 * 
	 * @param event
	 *            the event to fire
	 */
	protected void fireEvent(GUIEvent event) {
		synchronized (observers) {
			for (Observer<GUIEvent> observer : observers) {
				observer.notify(this, event);
			}
		}
	}

	@Override
	public void addObserver(Observer<GUIEvent> observer) {
		synchronized (observers) {
			observers.add(observer);
		}
	}

	@Override
	public void removeObserver(Observer<GUIEvent> observer) {
		synchronized (observers) {
			observers.remove(observer);
		}
	}

	@Override
	public JPanel getControlPanel() {
		while (panel_browser_initalized.getCount() > 0)
			try {
				panel_browser_initalized.await();
			} catch (InterruptedException e) {
				// ignore
			}
		return panel_browser;
	}
}
